import utils from '@/utils/utils'
import { useUserStore } from '@/stores/userInfo.js'

// 解析指令参数
function parseBinding(binding) {
  let options = {}

  if (typeof binding.value === 'function') {
    options.callback = binding.value
  } else if (typeof binding.value === 'object') {
    options = { ...binding.value }
  }

  return options
}

export function defineDirectives(app) {
  //监听挂载元素节点的尺寸变化
  app.directive('resize', {
    mounted(el, binding) {
      el.ob = new ResizeObserver((entries) => {
        for (const entry of entries) {
          if (entry.target === el) {
            if (binding.value && typeof binding.value === 'function') {
              binding.value({
                height: entry.borderBoxSize[0]['blockSize'],
                width: entry.borderBoxSize[0]['inlineSize'],
              })
            }
          }
        }
      })
      el.ob.observe(el)
    },
    unmounted(el, binding) {
      if (el.ob) {
        el.ob.disconnect()
        el.ob = null
        delete el.ob
      }
    },
  })

  app.directive('load-more', {
    mounted(el, binding) {
      const {
        // 默认配置
        target = '', // 要监听的滚动容器选择器
        distance = 100, // 距离底部多少像素触发
        delay = 200, // 节流时间(ms)
        callback, // 必须传入的回调函数
        immediate = false, // 是否立即初始化
      } = parseBinding(binding)

      // 元素引用缓存
      let scrollContainer = null
      let isLocked = false // 加载锁防止重复触发

      // 获取实际滚动容器
      const getScrollContainer = () => {
        if (!scrollContainer) {
          scrollContainer = target ? el.querySelector(target) : el
        }
        return scrollContainer
      }

      // 触底检测逻辑
      const checkBottom = utils.debounce(() => {
        if (isLocked) return

        const container = getScrollContainer()
        if (!container) return

        const { scrollTop, scrollHeight, clientHeight } = container
        const shouldLoad = scrollTop + clientHeight >= scrollHeight - distance

        if (shouldLoad) {
          isLocked = true
          Promise.resolve(callback?.()).finally(() => {
            isLocked = false
          })
        }
      }, delay)

      // 初始化监听
      const init = () => {
        const container = getScrollContainer()
        if (!container) return

        container.addEventListener('scroll', checkBottom)
        // 首次主动检查（适用于内容不满屏的情况）
        if (immediate) checkBottom()
      }

      // 清理监听
      const destroy = () => {
        const container = getScrollContainer()
        if (container) {
          container.removeEventListener('scroll', checkBottom)
        }
      }

      // 存储到元素属性以便更新和卸载
      el._loadMore = { init, destroy }

      // 延迟初始化确保 DOM 渲染完成
      setTimeout(init, 0)
    },

    updated(el, binding) {
      // 参数变化时重新初始化
      if (binding.value !== binding.oldValue) {
        el._loadMore?.destroy()
        el._loadMore?.init()
      }
    },

    beforeUnmount(el) {
      el._loadMore?.destroy()
    },
  })

  /**
   * 按钮权限指令
   * 使用方式：
   *   v-permission="'sys:user:add'" 单个权限
   *   v-permission="['sys:user:add', 'sys:user:edit']" 多个权限(或关系)
   *   v-permission.and="['sys:user:add', 'sys:user:edit']" 多个权限(与关系)
   */
  app.directive('permission', {
    mounted(el, binding) {
      const userStore = useUserStore()
      const { value, modifiers } = binding

      if (!value) return

      // 获取用户权限列表
      const permissions = userStore.permissions || []

      // 检查权限
      let hasPermission = false

      if (Array.isArray(value)) {
        // 数组类型权限检查
        if (modifiers.and) {
          // 必须拥有所有权限
          hasPermission = value.every((perm) => permissions.includes(perm))
        } else {
          // 拥有任一权限即可
          hasPermission = value.some((perm) => permissions.includes(perm))
        }
      } else if (typeof value === 'string') {
        // 单个权限检查
        hasPermission = permissions.includes(value)
      }
      // 没有权限则移除元素
      if (!hasPermission) {
        el.parentNode?.removeChild(el)
      }
    },
  })
  //防止按钮快速点击
  app.directive('prevent-reclick', {
    mounted(el, binding) {
      const customClassName = 'is-disabled'
      const delay = binding.value?.delay || 1000 // 默认防抖时间1.5秒
      function handleClick() {
        if (el.classList.contains(customClassName)) return

        // 禁用按钮
        el.classList.add(customClassName)
        el.disabled = true

        // 设置计时器并保存引用
        el._vp_timer = setTimeout(() => {
          el.classList.remove(customClassName)
          el.disabled = false
          clearTimeout(el._vp_timer)
          el._vp_timer = null
        }, delay)
      }

      el.addEventListener('click', handleClick)

      // 保存事件引用便于卸载
      el._vp_clickHandler = handleClick
    },
    unmounted(el) {
      // 清理定时器
      if (el._vp_timer) {
        clearTimeout(el._vp_timer)
        el._vp_timer = null
      }
      // 移除事件监听
      if (el._vp_clickHandler) {
        el.removeEventListener('click', el._vp_clickHandler)
      }
    },
  })
}
